home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 007 / makecode.lqr / makecode.lbr / MAKE2.C < prev   
Encoding:
Text File  |  2011-01-29  |  23.2 KB  |  1,154 lines

  1.  
  2.  
  3. /***** acf4:net.micro.pc / watrose!jmsellens /  5:08 am  Apr  7, 1984*/
  4.  
  5. X - bug killer
  6.  
  7.  
  8.  
  9. Here is the source for my version of a very simple 'Make' for
  10.  
  11. the IBM PC.  It requires DOS 2.0, and 'Path' and 'Find' (see
  12.  
  13. adjacent articles).  See below if you need a compiled version
  14.  
  15. on a floppy.  See below details, etc.  Sorry about the length
  16.  
  17. but I hope it's of use.  -  John
  18.  
  19. -------------------------------------------------------------
  20.  
  21. /*
  22.  
  23.         This a called 'Make' and is a much simplified version of
  24.  
  25.         the make utility on UNIX (a trademark or something of AT&T)
  26.  
  27.         written using the DeSmet C compiler/assembler and editor
  28.  
  29.         for the IBM Personal Computer.  The DeSmet package is
  30.  
  31.         available from C Ware, P.O. Box 710097, San Jose, California,
  32.  
  33.         95171-0097, (408) 736-6905 for around $100US.  I think it's
  34.  
  35.         a good deal.
  36.  
  37.  
  38.  
  39.         'Make' takes a file of dependencies (a 'makefile') and
  40.  
  41.         decides what commands have to be executed to bring the files
  42.  
  43.         up to date.  These commands are either executed directly from
  44.  
  45.         'Make' or written to the standard output without executing
  46.  
  47.         them.
  48.  
  49.  
  50.  
  51. 'Makefile' format:
  52.  
  53.         - There must be a 'makefile'; you can't take input from the
  54.  
  55.         standard input.
  56.  
  57.         - The default name of the 'makefile' is 'MAKEFILE.DAT' on the
  58.  
  59.         default disk.  Different 'makefiles' can be specified using
  60.  
  61.         the '-f' option on the command line.  If the '-f' option is
  62.  
  63.         used, the default 'makefile' is not processed.
  64.  
  65.         - Any blank lines in the 'makefile(s)' are ignored.
  66.  
  67.         - A line in a 'makefile' that starts with a tab character is
  68.  
  69.         a 'howto' line and consists of a command name followed by
  70.  
  71.         arguments.  The command name must be a full file name, e.g.
  72.  
  73.         'cc.exe'.  When commands are executed, the PATH environment
  74.  
  75.         variable is used to find the command, in (hopefully) the
  76.  
  77.         same manner as DOS does.  If a command name contains a ':'
  78.  
  79.         or a '\', it is assumed to be a complete pathname and the
  80.  
  81.         PATH is not searched.  'Howto' lines apply to the most
  82.  
  83.         recently preceding 'dependency' line.  It is an error for
  84.  
  85.         a 'howto' line to precede the first 'dependency' line.
  86.  
  87.         - Any other non-blank line is a 'dependency' line.  'Dependency'
  88.  
  89.         lines consist of a filename followed by a (possibly empty) list
  90.  
  91.         of dependent filenames.
  92.  
  93.  
  94.  
  95. Operation:
  96.  
  97.         Syntax:
  98.  
  99.                 make [filename] [-f makefilename] [-i] [-n]
  100.  
  101.         -i means continue even if an error is encountered while
  102.  
  103.                 executing a command.
  104.  
  105.         -n means don't execute the commands, just write the ones that
  106.  
  107.                 should be executed to the standard output.  This is useful
  108.  
  109.                 for creating batch files, for example.
  110.  
  111.         -f specifies that the following argument is the name of a makefile
  112.  
  113.                 to be used instead of the default (MAKEFILE.DAT).
  114.  
  115.         All arguments may be repeated and relative position of the
  116.  
  117.         arguments is not important.  If multiple definitions of a file
  118.  
  119.         are found, only the first one is significant.
  120.  
  121.  
  122.  
  123.         First, 'Make' reads all of the makefiles.  It then proceeds through
  124.  
  125.         all of the filename arguments, 'making' each one in turn.  A file
  126.  
  127.         is remade if it is out of date with respect to the files it depends
  128.  
  129.         on or is non-existent.  Dependencies are processed in a 'tree' fashion,
  130.  
  131.         so that the lowest-order files are remade first.
  132.  
  133.  
  134.  
  135.         'Make' cannot execute DOS built-in commands e.g. 'cd' or 'dir'.
  136.  
  137.         'Make' uses the first 75k or so after the resident portion of DOS.
  138.  
  139.         64k of that is stack and heap space: all definitions and howto's
  140.  
  141.         are stored in dynamically allocated struct's.  Any executed commands
  142.  
  143.         are loaded above 'Make' in memory.
  144.  
  145.  
  146.  
  147.         'Make' REQUIRES DOS 2.0 (or higher?).
  148.  
  149.  
  150.  
  151.         'Make' requires 'Find' and 'Path' in order to search the PATH.
  152.  
  153.         These are in (hopefully) adjacent articles.
  154.  
  155.  
  156.  
  157.  
  158.  
  159.    Known portability problems:
  160.  
  161.                 - assembler code embedded in the C code
  162.  
  163.                 - uses 'exec()' to execute the commands.
  164.  
  165.                 - 'Path' requires that code segment register (CS) be set to the
  166.  
  167.                   same value as at program invocation so that the
  168.  
  169.                   program segment prefix can be located.  This would
  170.  
  171.                   probably only be a problem if a "large model"
  172.  
  173.                   compiler is used.
  174.  
  175.  
  176.  
  177.         The code is a little kludgy in places.
  178.  
  179.  
  180.  
  181.         No guarantees or warranties of any kind:  I think it works and
  182.  
  183.         I use it.
  184.  
  185.  
  186.  
  187.         Any suggestions for improvements gratefully accepted.
  188.  
  189.  
  190.  
  191.         I believe that commercial versions exist.  I also beleive that they
  192.  
  193.         would be superior to this.
  194.  
  195.  
  196.  
  197.         If you do not have DeSmet C, I am willing to provide source,
  198.  
  199.         object, and linked files for 'Make', 'Find' and 'Path' for a price.
  200.  
  201.         Send me a floppy in a sturdy mailer, and $15 (you can tell I really
  202.  
  203.         don't want to do this, but I will), and I will return your disk to you.
  204.  
  205.         The $15 includes postage back to you.
  206.  
  207.  
  208.  
  209.  
  210.  
  211. */
  212.  
  213.  
  214.  
  215.  
  216.  
  217. /*
  218.  
  219. Written by John M Sellens, April, 1984
  220.  
  221.  
  222.  
  223. Code is all original except where indicated otherwise.
  224.  
  225.  
  226.  
  227. Until August, 1984:
  228.  
  229.         jmsellens@watrose.UUCP
  230.  
  231.  
  232.  
  233.         107 - 180 Brybeck Cres.
  234.  
  235.         Kitchener, Ontario
  236.  
  237.         N2M 5G4
  238.  
  239.  
  240.  
  241. After August, 1984:
  242.  
  243.         c/o 1135 Lansdowne Ave. SW
  244.  
  245.         Calgary, Alberta
  246.  
  247.         T2S 1A4
  248.  
  249.  
  250.  
  251. (c) Copyright 1984 John M Sellens
  252.  
  253. Permission is granted to use, distribute and/or modify this code unless
  254.  
  255. done for direct commercial profit.  If you find these routines useful,
  256.  
  257. modest contributions (monetary or otherwise) will be gratefully accepted.
  258.  
  259. Author's name, address and this notice must be included in any copies.
  260.  
  261.  
  262.  
  263. */
  264.  
  265.  
  266.  
  267.  
  268.  
  269.  
  270.  
  271. #include <stdio.h>
  272.  
  273.  
  274.  
  275. #define DEFAULT "MAKEFILE.DAT"
  276.  
  277. #define INMAX   130             /* maximum input line length */
  278.  
  279.  
  280.  
  281. struct howrec {
  282.  
  283.         char *howcom,*howargs;
  284.  
  285.         struct howrec *nexthow;
  286.  
  287. };
  288.  
  289.  
  290.  
  291. struct deprec {
  292.  
  293.         char *name;
  294.  
  295.         struct defnrec *def;
  296.  
  297.         struct deprec *nextdep;
  298.  
  299. };
  300.  
  301.  
  302.  
  303. struct defnrec {
  304.  
  305.         char *name;
  306.  
  307.         int uptodate;
  308.  
  309.         long modified;
  310.  
  311.         struct deprec *dependson;
  312.  
  313.         struct howrec *howto;
  314.  
  315.         struct defnrec *nextdefn;
  316.  
  317. };
  318.  
  319.  
  320.  
  321. struct dorec {
  322.  
  323.         char *name;
  324.  
  325.         struct dorec *nextdo;
  326.  
  327. };
  328.  
  329.  
  330.  
  331. struct defnrec *defnlist;
  332.  
  333. struct dorec *dolist;
  334.  
  335.  
  336.  
  337. int execute;
  338.  
  339. int stopOnErr;
  340.  
  341. int madesomething;
  342.  
  343. int knowhow;
  344.  
  345.  
  346.  
  347. main(argc,argv)
  348.  
  349. int argc;
  350.  
  351. char *argv[];
  352.  
  353. {
  354.  
  355.         long make();
  356.  
  357.  
  358.  
  359.         init(argc,argv);
  360.  
  361.  
  362.  
  363.         /* now fall down the dolist and do them all */
  364.  
  365.         while (dolist != NULL) {
  366.  
  367.                 madesomething = FALSE;
  368.  
  369.                 (void)make(dolist->name);       /* ignore return value */
  370.  
  371.                 if (!madesomething) {
  372.  
  373.                         if (knowhow)
  374.  
  375.                                 fprintf(stderr,"Make: '%s' is up to date\n",dolist->name);
  376.  
  377.                         else {
  378.  
  379.                                 fprintf(stderr,"Make: Don't know how to make '%s'\n",
  380.  
  381.                                         dolist->name);
  382.  
  383.                                 if (stopOnErr)
  384.  
  385.                                         exit(-1);
  386.  
  387.                         }
  388.  
  389.                 }
  390.  
  391.                 dolist = dolist->nextdo;
  392.  
  393.         }
  394.  
  395.  
  396.  
  397. }
  398.  
  399.  
  400.  
  401.  
  402.  
  403. init(argc,argv)
  404.  
  405. int argc;
  406.  
  407. char *argv[];
  408.  
  409. {
  410.  
  411.         int i, usedefault;
  412.  
  413.         dolist = NULL;
  414.  
  415.         defnlist = NULL;
  416.  
  417.         usedefault = TRUE;
  418.  
  419.         execute = TRUE;
  420.  
  421.         stopOnErr = TRUE;
  422.  
  423.  
  424.  
  425.         for (i=1; i < argc; i++) {
  426.  
  427.                 if (argv[i][0] == '-') {        /* option */
  428.  
  429.                         switch (argv[i][1]) {
  430.  
  431.                                 case 'f': case 'F':     /* arg following is a makefile */
  432.  
  433.                                         if (++i < argc) {
  434.  
  435.                                                 readmakefile(argv[i]);
  436.  
  437.                                                 usedefault = FALSE;
  438.  
  439.                                         } else {
  440.  
  441.                                                 fprintf(stderr,"Make: '-f' requires filename\n");
  442.  
  443.                                                 exit(-1);
  444.  
  445.                                         }
  446.  
  447.                                         break;
  448.  
  449.                                 case 'i': case 'I':     /* ignore errors on execution */
  450.  
  451.                                         stopOnErr = FALSE;
  452.  
  453.                                         break;
  454.  
  455.                                 case 'n': case 'N':     /* don't execute commands - just print */
  456.  
  457.                                         execute = FALSE;
  458.  
  459.                                         break;
  460.  
  461.                                 default:
  462.  
  463.                                         fprintf(stderr,"Make: unknown option '%s'\n",argv[i]);
  464.  
  465.                         }
  466.  
  467.                 } else {        /* it must be something to make */
  468.  
  469.                         add_do(argv[i]);
  470.  
  471.                 }
  472.  
  473.         }
  474.  
  475.         if (usedefault)
  476.  
  477.                 readmakefile(DEFAULT);
  478.  
  479.  
  480.  
  481. }
  482.  
  483.  
  484.  
  485. long make(s)    /* returns the modified date/time */
  486.  
  487. char *s;
  488.  
  489. {
  490.  
  491.         struct defnrec *defnp;
  492.  
  493.         struct deprec *depp;
  494.  
  495.         struct howrec *howp;
  496.  
  497.         long latest, getmodified(), max(), currtime();
  498.  
  499.  
  500.  
  501.         /* look for the definition */
  502.  
  503.         defnp = defnlist;
  504.  
  505.         while (defnp != NULL) {
  506.  
  507.                 if (strcmp(defnp->name,s) == 0)
  508.  
  509.                         break;
  510.  
  511.                 defnp = defnp->nextdefn;
  512.  
  513.         }
  514.  
  515.  
  516.  
  517.         if (defnp == NULL) {    /* don't know how to make it */
  518.  
  519.                 knowhow = FALSE;
  520.  
  521.                 latest = getmodified(s);
  522.  
  523.                 if (latest==0) {        /* doesn't exist but don't know how to make */
  524.  
  525.                         fprintf(stderr,"Make: Can't make '%s'\n",s);
  526.  
  527.                         exit(-1);
  528.  
  529.                 } else  /* exists - assume it's up to date since we don't know */
  530.  
  531.                         return(latest);
  532.  
  533.         }
  534.  
  535.  
  536.  
  537.         if (defnp->uptodate)
  538.  
  539.                 return(defnp->modified);
  540.  
  541.  
  542.  
  543.         /* now make sure everything that it depends on is up to date */
  544.  
  545.         latest = 0;
  546.  
  547.         depp = defnp->dependson;
  548.  
  549.         while (depp != NULL) {
  550.  
  551.                 latest = max(make(depp->name),latest);
  552.  
  553.                 depp = depp->nextdep;
  554.  
  555.         }
  556.  
  557.  
  558.  
  559.         knowhow = TRUE; /* has dependencies therefore we know how */
  560.  
  561.  
  562.  
  563.         /* if necessary, execute all of the commands to make it */
  564.  
  565.         /* if (out of date) || (depends on nothing)             */
  566.  
  567.         if (latest > defnp->modified || defnp->dependson==NULL) {
  568.  
  569.                 /* make those suckers */
  570.  
  571.                 howp = defnp->howto;
  572.  
  573.                 while (howp != NULL) {
  574.  
  575.                         printf("%s %s\n",howp->howcom,howp->howargs);
  576.  
  577.                         if (execute) {
  578.  
  579.                                 char filename[100];     /* extra space */
  580.  
  581.                                 if (find(howp->howcom,filename)) {
  582.  
  583.                                         if (exec(filename,howp->howargs) != 0) {
  584.  
  585.                                                 fprintf(stderr,"\nMake: error on '%s %s'",
  586.  
  587.                                                                 filename,howp->howargs);
  588.  
  589.                                                 if (stopOnErr)
  590.  
  591.                                                         exit(-1);
  592.  
  593.                                         }
  594.  
  595.                                 } else {
  596.  
  597.                                         fprintf(stderr,"\nMake: Can't find '%s'\n",
  598.  
  599.                                                 howp->howcom);
  600.  
  601.                                         if (stopOnErr)
  602.  
  603.                                                 exit(-1);
  604.  
  605.                                 }
  606.  
  607.                                 putchar('\n');  /* in case command leaves us dangling */
  608.  
  609.                         }
  610.  
  611.                         howp = howp->nexthow;
  612.  
  613.                 }
  614.  
  615.                 defnp->modified = currtime();
  616.  
  617.                 defnp->uptodate = TRUE;
  618.  
  619.                 if (defnp->howto != NULL)       /* we had instructions */
  620.  
  621.                         madesomething = TRUE;
  622.  
  623.         }
  624.  
  625.  
  626.  
  627.         return(defnp->modified);
  628.  
  629.  
  630.  
  631. }
  632.  
  633.  
  634.  
  635.  
  636.  
  637. add_do(s)
  638.  
  639. char *s;
  640.  
  641. {
  642.  
  643.         struct dorec *ptr1, *ptr2;
  644.  
  645.         char *getmem();
  646.  
  647.  
  648.  
  649.         ptr1 = getmem(sizeof(struct dorec));
  650.  
  651.  
  652.         ptr1->name = s; /* okay since only called with an argv */
  653.  
  654.         ptr1->nextdo = NULL;
  655.  
  656.  
  657.  
  658.         uppercase(ptr1->name);
  659.  
  660.  
  661.  
  662.         /* now go down the dolist */
  663.  
  664.         if (dolist == NULL)
  665.  
  666.                 dolist = ptr1;
  667.  
  668.         else {
  669.  
  670.                 ptr2 = dolist;
  671.  
  672.                 while (ptr2->nextdo != NULL)
  673.  
  674.                         ptr2 = ptr2->nextdo;
  675.  
  676.                 ptr2->nextdo = ptr1;
  677.  
  678.         }
  679.  
  680.  
  681.  
  682. }
  683.  
  684.  
  685.  
  686.  
  687.  
  688. readmakefile(s)
  689.  
  690. char *s;
  691.  
  692. {
  693.  
  694.         int fil, doneline, pos, i, j;
  695.  
  696.         char inline[INMAX], info[INMAX];
  697.  
  698.         char *getmem();
  699.  
  700.         struct defnrec *defnp, *defnp2;
  701.  
  702.         struct deprec *depp, *depp2;
  703.  
  704.         struct howrec *howp, *howp2;
  705.  
  706.  
  707.  
  708.         if ( (fil = open(s,0)) < 0) {
  709.  
  710.                 fprintf(stderr,"Make: Couldn't open '%s'\n",s);
  711.  
  712.                 return;
  713.  
  714.         }
  715.  
  716.  
  717.  
  718.         while (fgets(inline,INMAX,fil) != NULL) {
  719.  
  720.                 inline[strlen(inline)-1] = '\0';        /* strip trailing newline */
  721.  
  722.  
  723.  
  724.                 if (inline[0] == '\0')  /* ignore blank lines */
  725.  
  726.                         continue;
  727.  
  728.  
  729.  
  730.                 if (inline[0] != '\t') {        /* start of a new definition */
  731.  
  732.                         uppercase(inline);
  733.  
  734.  
  735.  
  736.                         /* get what we're defining into info */
  737.  
  738.                         if (sscanf(inline,"%s ",info) != 1) {
  739.  
  740.                                 fprintf(stderr,"Make: Can't scan: '%s'\n",inline);
  741.  
  742.                                 continue;
  743.  
  744.                         }
  745.  
  746.                         /* get a new struct */
  747.  
  748.                         defnp = getmem(sizeof(struct defnrec));
  749.  
  750.                         /* add it to the end of defnlist */
  751.  
  752.                         if (defnlist == NULL)
  753.  
  754.                                 defnlist = defnp;
  755.  
  756.                         else {
  757.  
  758.                                 defnp2 = defnlist;
  759.  
  760.                                 while (defnp2->nextdefn != NULL)
  761.  
  762.                                         defnp2 = defnp2->nextdefn;
  763.  
  764.                                 defnp2->nextdefn = defnp;
  765.  
  766.                         }
  767.  
  768.                         /* initialize it */
  769.  
  770.                         defnp->name = getmem(strlen(info)+1);
  771.  
  772.                         strcpy(defnp->name,info);
  773.  
  774.                         defnp->uptodate = FALSE;        /* actually unknown */
  775.  
  776.                         defnp->modified = getmodified(defnp->name);
  777.  
  778.                         defnp->dependson = NULL;
  779.  
  780.                         defnp->howto = NULL;
  781.  
  782.                         defnp->nextdefn = NULL;
  783.  
  784.  
  785.  
  786.                         /* now go through all of its dependecies */
  787.  
  788.                         /* first move past the first name */
  789.  
  790.                         pos = 0;
  791.  
  792.                         while (isspace(inline[pos]))
  793.  
  794.                                 pos++;
  795.  
  796.                         while (!isspace(inline[pos]) && inline[pos]!='\0')
  797.  
  798.                                 pos++;
  799.  
  800.                         /* now loop through those suckers */
  801.  
  802.                         doneline = FALSE;
  803.  
  804.                         while (!doneline) {
  805.  
  806.                                 while (isspace(inline[pos]))
  807.  
  808.                                         pos++;
  809.  
  810.                                 if (inline[pos] == '\0') {
  811.  
  812.                                         doneline = TRUE;
  813.  
  814.                                         continue;
  815.  
  816.                                 }
  817.  
  818.                                 for(i = 0; !isspace(inline[pos]) && inline[pos]!='\0'; )
  819.  
  820.                                         info[i++] = inline[pos++];
  821.  
  822.                                 info[i] = '\0';
  823.  
  824.                                 /* get a new struct */
  825.  
  826.                                 depp = getmem(sizeof(struct deprec));
  827.  
  828.                                 /* add it to the end of deplist */
  829.  
  830.                                 if (defnp->dependson == NULL)
  831.  
  832.                                         defnp->dependson = depp;
  833.  
  834.                                 else {
  835.  
  836.                                         depp2 = defnp->dependson;
  837.  
  838.                                         while (depp2->nextdep != NULL)
  839.  
  840.                                                 depp2 = depp2->nextdep;
  841.  
  842.                                         depp2->nextdep = depp;
  843.  
  844.                                 }
  845.  
  846.                                 depp->name = getmem(strlen(info)+1);
  847.  
  848.                                 strcpy(depp->name,info);
  849.  
  850.                                 depp->nextdep = NULL;
  851.  
  852.                         }
  853.  
  854.                 } else {        /* a how to line */
  855.  
  856.                         if (defnp == NULL) {
  857.  
  858.                                 fprintf(stderr,"Make: Howto line without a definition\n");
  859.  
  860.                                 fprintf(stderr,"Make: '%s'\n",inline);
  861.  
  862.                         }
  863.  
  864.                         /* now split the line up into command and args */
  865.  
  866.                         for (pos=0;isspace(inline[pos]); pos++);
  867.  
  868.                                 ;
  869.  
  870.                         for (i=pos; !isspace(inline[i]) && inline[i]!='\0'; i++)
  871.  
  872.                                 ;
  873.  
  874.                         /* if there is something there, allocate mem and copy */
  875.  
  876.                         if (i != pos) {
  877.  
  878.                                 /* get a new struct */
  879.  
  880.                                 howp = getmem(sizeof(struct howrec));
  881.  
  882.                                 /* add it to the end of howlist */
  883.  
  884.                                 if (defnp->howto == NULL)
  885.  
  886.                                         defnp->howto = howp;
  887.  
  888.                                 else {
  889.  
  890.                                         howp2 = defnp->howto;
  891.  
  892.                                         while (howp2->nexthow != NULL)
  893.  
  894.                                                 howp2 = howp2->nexthow;
  895.  
  896.                                         howp2->nexthow = howp;
  897.  
  898.                                 }
  899.  
  900.                                 /* copy command filename */
  901.  
  902.                                 howp->howcom = getmem(i-pos+1);
  903.  
  904.                                 for(j=0; pos < i; )
  905.  
  906.                                         howp->howcom[j++] = inline[pos++];
  907.  
  908.                                 howp->howcom[j] = '\0';
  909.  
  910.                                 /* now look for any argumentative part */
  911.  
  912.                                 while (isspace(inline[pos]))
  913.  
  914.                                         pos++;
  915.  
  916.                                 howp->howargs = getmem(strlen(inline)-pos + 1);
  917.  
  918.                                 for(i=0; inline[pos] != '\0'; )
  919.  
  920.                                         howp->howargs[i++] = inline[pos++];
  921.  
  922.                                 howp->howargs[i] = '\0';
  923.  
  924.                                 howp->nexthow = NULL;
  925.  
  926.                         }
  927.  
  928.                 }
  929.  
  930.         }
  931.  
  932. }
  933.  
  934.  
  935.  
  936.  
  937.  
  938. uppercase(s)
  939.  
  940. char *s;
  941.  
  942. {
  943.  
  944.         for( ; *s != '\0'; s++)
  945.  
  946.                 *s = toupper(*s);
  947.  
  948. }
  949.  
  950.  
  951.  
  952.  
  953.  
  954. char *getmem(size)
  955.  
  956. int size;
  957.  
  958. {
  959.  
  960.         char *p;
  961.  
  962.         if ((p = malloc(size)) == 0) {
  963.  
  964.                 fprintf(stderr,"Make: Ran out of memory...\n");
  965.  
  966.                 exit(-1);
  967.  
  968.         }
  969.  
  970.         return(p);
  971.  
  972. }
  973.  
  974.  
  975.  
  976.  
  977.  
  978. long getmodified(name)
  979.  
  980. char *name;
  981.  
  982. {
  983.  
  984.         int fil;
  985.  
  986.         long d, dateof();
  987.  
  988.         if ((fil=open(name,0)) >= 0) {  /* file exists and was opened */
  989.  
  990.                 d = dateof(fil);
  991.  
  992.                 close(fil);
  993.  
  994.         } else  /* doesn't exist so set very low date */
  995.  
  996.                 d = 0;
  997.  
  998.         return(d);
  999.  
  1000. }
  1001.  
  1002.  
  1003.  
  1004. long dateof(fil)
  1005.  
  1006. /*      return a long encoding the date and time of a file      */
  1007.  
  1008. /*  stolen from DeSmet C distribution                   */
  1009.  
  1010. int  fil;
  1011.  
  1012. {
  1013.  
  1014.         static long ret_dt;
  1015.  
  1016.  
  1017.  
  1018. #asm
  1019.  
  1020.         mov             bx,[bp+4]                               ;file handle is here. only argument.
  1021.  
  1022.         and             bx,0ffh                                 ;low byte of file id is MS-DOS handle.
  1023.  
  1024.         mov             al,0                                    ;code to retrieve date and time.
  1025.  
  1026.         mov             ah,57h                                  ;dos code for get file date and time.
  1027.  
  1028.         int             21h                                             ;call dos.
  1029.  
  1030.         mov             word dateof_ret_dt_+2,dx;store date in high word of ret_dt.
  1031.  
  1032.         mov             word dateof_ret_dt_,cx  ;store time in low word of ret_dt.
  1033.  
  1034.                                                                         ;note: "dateof_" is added to name
  1035.  
  1036.                                                                         ;because ret_dt is static.
  1037.  
  1038. #
  1039.  
  1040.         return ret_dt;
  1041.  
  1042. }
  1043.  
  1044.  
  1045.  
  1046. long currtime()
  1047.  
  1048. /* return a long encoding the current date and time */
  1049.  
  1050. {
  1051.  
  1052.         static long ret_dt;
  1053.  
  1054.  
  1055.  
  1056. #asm
  1057.  
  1058.         mov             ah,2Ah                                  ;dos code for get date
  1059.  
  1060.         int             21h                                             ;call dos.
  1061.  
  1062.         sbb             cx,1980
  1063.  
  1064.         mov             ax,cx                                   ;year
  1065.  
  1066.         shl             ax,1
  1067.  
  1068.         shl             ax,1
  1069.  
  1070.         shl             ax,1
  1071.  
  1072.         shl             ax,1
  1073.  
  1074.         or              al,dh                                   ;month
  1075.  
  1076.         shl             ax,1
  1077.  
  1078.         shl             ax,1
  1079.  
  1080.         shl             ax,1
  1081.  
  1082.         shl             ax,1
  1083.  
  1084.         shl             ax,1
  1085.  
  1086.         or              al,dl                                   ;day
  1087.  
  1088.         mov             word currtime_ret_dt_+2,ax;store date in high word of ret_dt.
  1089.  
  1090.  
  1091.  
  1092.         mov             ah,2Ch                                  ;dos code for get time
  1093.  
  1094.         int             21h                                             ;call dos
  1095.  
  1096.         xor             ax,ax
  1097.  
  1098.         mov             al,ch                                   ;hours
  1099.  
  1100.         shl             ax,1
  1101.  
  1102.         shl             ax,1
  1103.  
  1104.         shl             ax,1
  1105.  
  1106.         shl             ax,1
  1107.  
  1108.         shl             ax,1
  1109.  
  1110.         shl             ax,1
  1111.  
  1112.         or              al,cl                                   ;minutes
  1113.  
  1114.         shl             ax,1
  1115.  
  1116.         shl             ax,1
  1117.  
  1118.         shl             ax,1
  1119.  
  1120.         shl             ax,1
  1121.  
  1122.         shl             ax,1
  1123.  
  1124.         shr             dx,1
  1125.  
  1126.         or              al,dh                                   ;number of two second increments
  1127.  
  1128.         mov             word currtime_ret_dt_,ax;store time in low word of ret_dt.
  1129.  
  1130.                                                                         ;note: "dateof_" is added to name
  1131.  
  1132.                                                                         ;because ret_dt is static.
  1133.  
  1134. #
  1135.  
  1136.         return ret_dt;
  1137.  
  1138. }
  1139.  
  1140.  
  1141.  
  1142. long max(a,b)
  1143.  
  1144. long a,b;
  1145.  
  1146. {
  1147.  
  1148.         return(a>b ? a : b);
  1149.  
  1150. }
  1151.  
  1152. /* ---------- */
  1153.  
  1154. %